package com.jz.community.basecomm.base;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;


/**
 * 基础的sharepreference
 */
public abstract class BaseSP {

    public static final String FILE_NAME = "share_data";


    /**
     * 每个模块保存到自己的sharepreference 文件下面
     *
     * @return
     */
    public abstract String getModelPreferenceFIleName();


    /**
     * 获取保存的文件名
     *
     * @return
     */
    private String getSavePerferenceFileName() {
        String fileName = getModelPreferenceFIleName();
        if (TextUtils.isEmpty(fileName)) {
            return FILE_NAME;
        } else {
            return fileName;
        }
    }

    /**
     * 移除某个key值已经对应的值
     *
     * @param context
     * @param key
     */
    public void remove(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(getSavePerferenceFileName(), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 清除所有数据
     *
     * @param context
     */
    public void clear(Context context) {
        SharedPreferences sp = context.getSharedPreferences(getSavePerferenceFileName(), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 查询某个key是否已经存在
     *
     * @param context
     * @param key
     * @return
     */
    public boolean contains(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(getSavePerferenceFileName(), Context.MODE_PRIVATE);
        return sp.contains(key);
    }

    /**
     * 返回所有的键值对
     *
     * @param context
     * @return
     */
    public Map<String, ?> getAll(Context context) {
        SharedPreferences sp = context.getSharedPreferences(getSavePerferenceFileName(), Context.MODE_PRIVATE);
        return sp.getAll();
    }

    /**
     * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
     *
     * @author zhy
     */
    private static class SharedPreferencesCompat {
        private static final Method sApplyMethod = findApplyMethod();

        /**
         * 反射查找apply的方法
         *
         * @return
         */
        @SuppressWarnings({"unchecked", "rawtypes"})
        private static Method findApplyMethod() {
            try {
                Class clz = SharedPreferences.Editor.class;
                return clz.getMethod("apply");
            } catch (NoSuchMethodException e) {
            }

            return null;
        }

        /**
         * 如果找到则使用apply执行，否则使用commit
         *
         * @param editor
         */
        public static void apply(SharedPreferences.Editor editor) {
            try {
                if (sApplyMethod != null) {
                    sApplyMethod.invoke(editor);
                    return;
                }
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            } catch (InvocationTargetException e) {
            }
            editor.commit();
        }
    }

    /**
     * 保存boolean类型的值通用
     *
     * @param context 上下文
     * @param key     要保存的键
     * @param value   键所对应的值
     */
    public void putBoolean(Context context, String key, boolean value) {
        putSpBoolean(context, getSavePerferenceFileName(), key, value);
    }

    /**
     * @param context 上下文
     * @param key     要查找的键
     * @return 默认返回false
     */
    public boolean getBoolean(Context context, String key) {
        return getSpBoolean(context, getSavePerferenceFileName(), key);
    }

    /**
     * 保存int类型的值通用
     *
     * @param context 上下文
     * @param key     要保存的键
     * @param value   键所对应的值
     */
    public void putInt(Context context, String key, int value) {
        putSpInt(context, getSavePerferenceFileName(), key, value);
    }

    /**
     * @param context
     * @param key
     * @return 默认返回0
     */
    public int getInt(Context context, String key) {
        return getSpInt(context, getSavePerferenceFileName(), key);
    }

    /**
     * 保存数据的方法，我们需要拿到保存数据的具体类型，然后根据类型调用不同的保存方法
     *
     * @param context
     * @param key
     */
    public void putString(Context context, String key, String value) {
        setSpString(context, getSavePerferenceFileName(), key, value);
    }


    /**
     * 得到保存数据的方法，我们根据默认值得到保存的数据的具体类型，然后调用相对于的方法获取值
     *
     * @param context
     * @param key
     * @return
     */
    public String getString(Context context, String key) {
        return getSpString(context, getSavePerferenceFileName(), key);
    }


    public static void putSpInt(Context context, String fileName, String key, int value) {
        SharedPreferences.Editor edit = context.getSharedPreferences(fileName, 0).edit();
        edit.putInt(key, value).apply();
    }

    public static void putSpBoolean(Context context, String fileName, String key, boolean value) {
        SharedPreferences.Editor edit = context.getSharedPreferences(fileName, 0).edit();
        edit.putBoolean(key, value).apply();
    }


    /**
     * 获取sp String Value
     *
     * @param context
     * @param fileName
     * @param key
     * @return
     */
    public static String getSpString(Context context, String fileName, String key) {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        return sp.getString(key, "");
    }

    /**
     * 设置sp String Value
     *
     * @param context
     * @param fileName
     * @param key
     * @return
     */
    public static void setSpString(Context context, String fileName, String key, String value) {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString(key, value);
        SharedPreferencesCompat.apply(editor);
    }

    public static int getSpInt(Context context, String fileName, String key) {
        SharedPreferences sp = context.getSharedPreferences(fileName, 0);
        return sp.getInt(key, 0);
    }

    public static boolean getSpBoolean(Context context, String fileName, String key) {
        SharedPreferences sp = context.getSharedPreferences(fileName, 0);
        return sp.getBoolean(key, false);
    }

    /**
     * 获取数据
     *
     * @param context
     * @param name
     * @param key
     * @return
     */
    public static String getString(Context context, String name, String key) {
        return getSpString(context, name, key);
    }

    /**
     * 添加数据到SharedPreferences
     *
     * @param context
     * @param name
     * @param key
     * @param value
     */
    public static void putString(Context context, String name,
                                 String key, String value) {
        setSpString(context, name, key, value);
    }

    /**
     * 得到保存数据的方法，我们根据默认值得到保存的数据的具体类型，然后调用相对于的方法获取值
     *
     * @param context
     * @param key
     * @return
     */
    public static String get(Context context, String key) {
        return getSpString(context, FILE_NAME, key);
    }

    /**
     * 保存数据的方法，我们需要拿到保存数据的具体类型，然后根据类型调用不同的保存方法
     *
     * @param context
     * @param key
     */
    public static void put(Context context, String key, String value) {
        setSpString(context, FILE_NAME, key, value);
    }

    public static byte[] StringToBytes(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }

    private static byte toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    public static String bytesToHexString(byte[] bArray) {
        if (bArray == null) {
            return null;
        }
        if (bArray.length == 0) {
            return "";
        }
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2){
                sb.append(0);
                sb.append(sTemp.toUpperCase());
            }
        }
        return sb.toString();
    }
}